﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace COMP376A3_9609695
{
    class GameController : Updates
    {
        public List<Block> blocks { get; private set;}
        public Ball player;
        private Model blockModel;
        public float dropInterval;
        private float timePassed;
        private float dropTimer;
        private float dropDist;
        float ballRadsq;
        float ballRad;
        Random r;
        public GameState state;
        public int maxDist;
        public bool infinite;
        private bool plumetted = false;

        public GameController(Ball player, Model blockModel)
        {
            this.player = player;
            this.blockModel = blockModel;
            blocks = new List<Block>();
            //blocks.Add(new Block(blockModel, 0f, 20f, 20f));
            dropInterval = 500f;
            timePassed = 0;
            dropTimer = 0;
            ballRadsq = Math.Abs((player.Y) * (2 - (player.Y)));
            ballRad = (float)Math.Sqrt(ballRadsq);
            r = new Random();
            state = GameState.StartScreen;
            dropDist = 55f;
            maxDist = 500;
            infinite = false;
        }

        public void Update(GameTime time)
        {
            int elapsed = time.ElapsedGameTime.Milliseconds;
            if (!infinite && player.Z >= maxDist && player.Y >= -1.0f && !plumetted)
            {
                player.plummet();
                plumetted = true;
            }
            if (state == GameState.Play)
            {
                dropTimer += elapsed;
                if (dropTimer >= dropInterval && (player.Z <= maxDist - dropDist && !infinite))
                {
                    dropTimer = 0;
                    float xPos = (float)r.NextDouble() * 5 - 2.5f + player.X;
                    if (xPos > 5)
                        xPos = 5;
                    if (xPos < -5)
                        xPos = -5;
                    blocks.Add(new Block(blockModel, xPos, 20f, player.Z + dropDist));
                    dropInterval = 1000 - player.maxmZ / 3 * 8 - 100;
                    if (dropInterval < 100)
                        dropInterval = 100;
                }
                timePassed += elapsed;

                int blockCount = blocks.Count;
                for (int b = 0; b < blockCount; b++)
                {
                    Block block = blocks.ElementAt(b);
                    if (block.Z < player.Z - 20)
                    {
                        blocks.Remove(block);
                        b--;
                        blockCount--;
                    }
                    block.colliding = false;
                    if (player.Y <= -0.5 && collides(block.X, block.Z, 2.0f, 1.0f, 2.0f))
                    {
                        block.colliding = true;
                    }
                    block.Update(time);
                }
            }
        }

        public bool collides(float boxX, float boxZ, float boxWidth, float boxHeight, float boxDepth)
        {
            if (player.Y <= -0.5f * player.radius)
            {
                if (boxHeight <= player.radius)
                    ballRadsq = Math.Abs(((player.Y + 2) - boxHeight + 1) * (2 * player.radius - ((player.Y + 2) - boxHeight + 1)));
                else
                    ballRadsq = player.radius * player.radius;
            }
            else
                ballRadsq = 0;
            ballRad = (float)Math.Sqrt(ballRadsq);

            float dX = Math.Abs(player.X - boxX);
            float dZ = Math.Abs(player.Z - boxZ);

            if (dX > boxWidth / 2 + ballRad)
                return false;
            if (dZ > boxDepth / 2 + ballRad)
                return false;

            if (dX <= boxWidth / 2)
                return true;
            if (dZ <= boxDepth / 2)
                return true;

            float cornerDistSq = (dX + boxWidth / 2) * (dX + boxWidth / 2) + (dZ + boxDepth / 2) * (dZ + boxDepth / 2);

            return cornerDistSq <= ballRadsq;
        }
    }
}
